# 导包
from numpy import *
import numpy as np
import pandas as pd
from sklearn import datasets
import matplotlib as mpl
import matplotlib.pyplot as plt
# sklearn库中实现kNN回归的模型有两个：
# KNeighborsRegressor(n_neighbors)：根据每个查询点的最近邻的k个数据点的均值作为预测值。
# RadiusNeighborsRegressor(radius)：基于查询点的固定半径内的数据点的均值作为预测值，radius一般指定浮点数。
from sklearn.neighbors import KNeighborsRegressor
from sklearn.neighbors import RadiusNeighborsRegressor

# 防止画图出现中文乱码
mpl.rcParams['font.family'] = 'simHei'
mpl.rcParams['axes.unicode_minus'] = False

# 加载数据
iris = datasets.load_iris()
print(iris)
data = pd.DataFrame(iris.data)
# 抽取行数和原行数相同，随机数种子=20，默认抽取行
data = data.sample(n=len(data), random_state=20)
# print(len(data)) # 150

train_x = np.asarray(data.iloc[:120, :-1])
train_y = np.asarray(data.iloc[:120, -1])

test_x = data.iloc[120:, :-1]
test_y = data.iloc[120:, -1]

# print(len(test_x))

plt.figure(figsize=(10, 10))
plt.plot(test_y.values, 'go--', label='真实值')
plt.title('kNN连续值预测')
plt.xlabel('节点序号')
plt.ylabel('花瓣宽度')
plt.legend()
plt.show()


# 手写kNN回归代码

def predict(test_X, train_X, train_y, k):
    result = []
    dataSetSize = train_X.shape[0]  # 查看矩阵的维度
    test_X = np.asarray(test_X)
    for x in test_X:
        '''
        diffMat = tile(x,(dataSetSize,1)) - train_X
        #tile(数组,(在行上重复次数,在列上重复次数))
        sqDiffMat = diffMat**2
        sqDistances = sqDiffMat.sum(axis=1)
        #sum默认axis=0，是普通的相加，axis=1是将一个矩阵的每一行向量相加
        distances = sqDistances**0.5
        '''
        distances = np.sqrt(np.sum((x - train_X) ** 2, axis=1))
        sortedDistIndicies = distances.argsort()
        index = sortedDistIndicies[:k]
        # sort函数按照数组值从小到大排序
        # argsort函数返回的是数组值从小到大的索引值
        result.append(np.mean(train_y[index]))

    return np.asarray(result)


# 进行预测
result = predict(test_x, train_x, train_y, 4)
print(result)

# 第四个属性的真实值
plt.figure(figsize=(10, 10))
plt.plot(result, 'ro--', label='预测值')
plt.plot(test_y.values, 'go--', label='真实值')
plt.title('kNN连续值预测')
plt.xlabel('节点序号')
plt.ylabel('花瓣宽度')
plt.legend()
plt.show()

kng = KNeighborsRegressor(n_neighbors=4)

kng.fit(train_x, train_y)
prediction = kng.predict(test_x)

plt.figure(figsize=(10, 10))
plt.plot(result, 'ro--', label='预测值1')
plt.plot(prediction, 'bo--', label='预测值2')
plt.plot(test_y.values, 'go--', label='真实值')
plt.title('kNN连续值预测')
plt.xlabel('节点序号')
plt.ylabel('花瓣宽度')
plt.legend()
plt.show()

kng1 = RadiusNeighborsRegressor(radius=1.0)
kng1.fit(train_x, train_y)
prediction1 = kng1.predict(test_x)

plt.figure(figsize=(10, 10))
plt.plot(result, 'ro--', label='预测值1')
plt.plot(prediction, 'bo--', label='预测值2')
plt.plot(prediction1, 'yo--', label='预测值3')
plt.plot(test_y.values, 'go--', label='真实值')
plt.title('kNN连续值预测')
plt.xlabel('节点序号')
plt.ylabel('花瓣宽度')
plt.legend()
plt.show()
